# pybotwar ubertweak tournament server

import datetime
import os
import random
import re

from skills import (
    GameInfo,
    Match,
    Matches,
    Team,
    )
from skills.glicko import GlickoCalculator

import conf
import stats
import util
import viewselect

viewselect.select_view_module('none')
view = viewselect.get_view_module()

from game import Game
import world



# run one battle
def run_one():
    
    # Get the challengers!
    stats.dbopen()
    q = '''
    SELECT
        owner,
        program_name,
        mean,
        stdev

    FROM stats
    WHERE
        buggy = 0
    ORDER BY playcount ASC
    '''
    stats.c.execute(q, locals())
    results = stats.c.fetchall()
    stats.dbclose()
    
    challengerA = results[0]
    challengerB = random.choice(results[1:])
    
    # Increment playcount
    q = '''\
        UPDATE stats
        SET playcount = playcount + 1
        WHERE
            owner = :owner AND
            program_name = :program_name'''
    stats.makequery(q, (challengerA[0], challengerA[1]))
    stats.makequery(q, (challengerB[0], challengerB[1]))
    
    # Run the battle
    conf.robots = [
        challengerA[0] + '_' + challengerA[1],
        challengerB[0] + '_' + challengerB[1]
    ]
    dt = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    game = Game(False, dt)
    game.run()
    world.Robot.nrobots = 0
    view.Robot.nrobots = 0
    
    # Identify the winner
    if game.rnd >= conf.maxtime*60:
        # ran out of time, so not stats update
        return
    elif game.models[challengerA[0] + '_' + challengerA[1]].alive:
        winner = [1, 2]
    else:
        winner = [2, 1]
    
    # Do our magical stats
    calculator = GlickoCalculator()
    game_info = GameInfo()
    player1 = Team({1: (challengerA[2], challengerA[3])})
    player2 = Team({2: (challengerB[2], challengerB[3])})
    matches = Matches([Match([player1, player2], winner)])
    new_ratings = calculator.new_ratings(game_info, matches, 1)
    
    # Update the ratings
    player1_rating = new_ratings.rating_by_id(1)
    player2_rating = new_ratings.rating_by_id(2)
    q = '''\
        UPDATE stats
        SET mean = :mean,
            stdev = :stdev
        WHERE
            owner = :owner AND
            program_name = :program_name'''
    stats.makequery(q, (player1_rating.mean, player1_rating.stdev, challengerA[0], challengerA[1]))
    stats.makequery(q, (player2_rating.mean, player2_rating.stdev, challengerB[0], challengerB[1]))
    
    
def start():
    try:
        print 'Starting pybotwar server'

        while True:
            run_one()
    except KeyboardInterrupt:
        print '\nStopping pybotwar server'
    
if __name__ == '__main__':
    start()
